library(Seurat)
library(monocle)
Loading required package: Biobase
Loading required package: BiocGenerics
Loading required package: parallel
Attaching package: ‘BiocGenerics’
The following objects are masked from ‘package:parallel’:
clusterApply, clusterApplyLB, clusterCall, clusterEvalQ,
clusterExport, clusterMap, parApply, parCapply, parLapply,
parLapplyLB, parRapply, parSapply, parSapplyLB
The following objects are masked from ‘package:Matrix’:
colMeans, colSums, rowMeans, rowSums, which
The following objects are masked from ‘package:stats’:
IQR, mad, sd, var, xtabs
The following objects are masked from ‘package:base’:
anyDuplicated, append, as.data.frame, basename, cbind, colMeans,
colnames, colSums, dirname, do.call, duplicated, eval, evalq,
Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply,
lengths, Map, mapply, match, mget, order, paste, pmax, pmax.int,
pmin, pmin.int, Position, rank, rbind, Reduce, rowMeans, rownames,
rowSums, sapply, setdiff, sort, table, tapply, union, unique,
unsplit, which, which.max, which.min
Welcome to Bioconductor
Vignettes contain introductory material; view with
'browseVignettes()'. To cite Bioconductor, see
'citation("Biobase")', and for packages 'citation("pkgname")'.
Loading required package: VGAM
Loading required package: stats4
Loading required package: splines
Loading required package: DDRTree
Loading required package: irlba
library(dplyr)
Attaching package: ‘dplyr’
The following object is masked from ‘package:Biobase’:
combine
The following objects are masked from ‘package:BiocGenerics’:
combine, intersect, setdiff, union
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(ggplot2)
library(ggrepel)
library(GOplot)
Loading required package: ggdendro
Loading required package: gridExtra
Attaching package: ‘gridExtra’
The following object is masked from ‘package:dplyr’:
combine
The following object is masked from ‘package:Biobase’:
combine
The following object is masked from ‘package:BiocGenerics’:
combine
Loading required package: RColorBrewer
seurobj <- readRDS('../output/seurat_objects/180831/10x-180831')
cds <- readRDS('output/monocle/180831/10x-180831-monocle-monocle_genelist_T1T2T3_T4T5_res.1.5')
cannot open compressed file 'output/monocle/180831/10x-180831-monocle-monocle_genelist_T1T2T3_T4T5_res.1.5', probable reason 'No such file or directory'Error in gzfile(file, "rb") : cannot open the connection
Figure 3
Heatmap
Heatmap
rr load(‘../output/monocle/180831/heatmaps’) heatmap <- heatmaps\(heatmap_logFC0.3_ncluster6_filtered_genes gridExtra::grid.arrange(heatmap\)ph_res$gtable)
rr save_plot(../figures/figures_paper/main_figures/figure3/BEAM_heatmap_logFC0.3_ncluster6_filtered_genes.pdf, heatmap\(ph_res\)gtable, base_width=7, base_height=8)
Pseudotime plots
Pseudotime plots
rr #new_cds <- buildBranchCellDataSet(cds, progenitor_method=‘duplicate’, branch_states=c(2,3), branch_point=1, branch_labels=c(‘Metabolic’, ‘ECM’), stretch=T) #saveRDS(new_cds, file=‘../output/monocle/180831/10x-180831-monocle-monocle_genelist_T1T2T3_T4T5_res.1.5_duplicated-progenitor_stretched-pseudotime’) #new_cds <- readRDS(‘../output/monocle/180831/10x-180831-monocle-monocle_genelist_T1T2T3_T4T5_res.1.5_duplicated-progenitor_stretched-pseudotime’) #new cds contains duplicated progenitor cells (one assigned to each branch) and stretched Pseudotime df_pdata <- pData(new_cds)[c(‘original_cell_id’, ‘Branch’, ‘State.labels’, ‘Pseudotime’)]
Error in pData(new_cds) : object 'new_cds' not found

rr width=6 height=5 save_plot(../figures/figures_paper/main_figures/figure3/pseudotime_ADIPOQ.pdf, adipoq_pt, base_width=width, base_height=height) save_plot(../figures/figures_paper/main_figures/figure3/pseudotime_UCP2.pdf, ucp2_pt, base_width=width, base_height=height) r save_plot(../figures/figures_paper/main_figures/figure3/pseudotime_DCN.pdf, dcn_pt, base_width=width, base_height=height) save_plot(../figures/figures_paper/main_figures/figure3/pseudotime_APOD.pdf, apod_pt, base_width=width, base_height=height)
Featureplots
genes <- c('ADIPOQ', 'UCP2', 'DCN', 'APOD')
featureplots_noleg <- FeaturePlot(seurobj, features.plot=genes, cols.use=c('gray', 'blue'), no.legend=T, do.return=T, no.axes=T, pt.size=1, max.cutoff=c(5))

featureplots_leg <- FeaturePlot(seurobj, features.plot=genes, cols.use=c('gray', 'blue'), no.legend=F, do.return=T, no.axes=T, pt.size=1, max.cutoff=c(5))

adipoq_fp <- featureplots_noleg$ADIPOQ + theme(plot.title=element_blank())
ucp2_fp <- featureplots$UCP2 + scale_color_gradient(name='Expression', low='gray', high='blue', guide='colorbar', limits=c(0,5)) + theme(plot.title=element_blank(), legend.title=element_text(size=20), legend.text=element_text(size=20), legend.key.height = unit(1.3, 'cm'))

save_plot("../figures/figures_paper/main_figures/Figure3_beam/featureplots_metabolic.pdf", metabolic_fp, base_width=width, base_height=height)
Error in save_plot("../figures/figures_paper/main_figures/Figure3_beam/featureplots_metabolic.pdf", :
object 'height' not found
GO bubble plot
name <- 'heatmap_logFC0.3_ncluster6'
folder <- paste('../tables/tables_paper/all_tables/BEAM/', name, sep='')
#clusters <- c(1,2,3,4,6)
clusters <- c(2,6,3)
gsea <- list()
genelist <- list()
for (i in clusters){
gsea_cluster <- read.table(paste(folder, '/REVIGO_cleaned/', 'REVIGO_cluster', i, '_cleaned.tsv', sep=''), header=T)
gsea_cluster['cluster'] <- i
genes_cluster <- read.table(paste(folder, '/genelist_cluster', i, '.tsv', sep=''), header=T)
gsea[[i]] <- gsea_cluster
genelist[[i]] <- genes_cluster
}
gsea <- do.call("rbind", gsea)
genelist <- do.call("rbind", genelist)
create_terms <- function(gsea){
return(data.frame(category=gsea$gsea.domain, ID=gsea$revigo.term_ID, term=gsea$revigo.description, adj_pval=gsea$gsea.p.value, genes=gsea$gsea.intersection, cluster=gsea$cluster))
}
create_genes <- function(genelist){
return(data.frame(ID=genelist$gene_short_name, logFC=genelist$avgLogFC_State2_State3))
}
terms <- create_terms(gsea)
genes <- create_genes(genelist)
circ <- circle_dat(terms, genes)

rr save_plot(‘../figures/figures_paper/main_figures/Figure3_beam/180831_beamGO_all-terms.pd_labels3_zscore4.5.pdf’, p, base_width=20, base_height=7)
Percent.mito
rr percent_mito_fp <- FeaturePlot(seurobj, features.plot=c(‘percent.mito.100’), cols.use=c(‘gray’, ‘blue’), no.legend=F, do.return=T, no.axes=T, max.cutoff = c(10))$percent.mito + ggtitle(‘’) + scale_color_gradient(name=’% mitochondrialexpression’, low=‘gray’, high=‘blue’, guide=‘colorbar’) + theme(legend.key.height = unit(1.6, ‘cm’))


rr save_plot(../figures/figures_paper/main_figures/figure3/featureplot_PERCENT_MITO.pdf, percent_mito_fp, base_width=width, base_height=height)
BATLAS
rr batlas_results <- read.table(‘../tables/tables_paper/supplementary_tables/BATLAS/BATLAS_branch_high_res.txt’, sep=‘’, header=T) batlas_results[‘pseudotime_decile’] <- seurobj@meta.data$pseudotime_decile[match(batlas_results\(sample, seurobj@meta.data\)branch_high_res)] batlas_results[‘branch’] <- seurobj@meta.data$branch[match(batlas_results\(sample, seurobj@meta.data\)branch_high_res)] batlas_results <- batlas_results %>% mutate(block_branch = if_else(branch == ‘Progenitor’, ‘Beginning’, ‘End’)) batlas_results[‘brown_centered’] <- batlas_results\(brown - 0.5 batlas_results['ratio'] <- batlas_results\)brown/batlas_results$white
rr p <- ggplot(batlas_results, aes(x=as.factor(pseudotime_decile), y=brown_centered, fill=branch)) + geom_col(position = position_dodge2(width=0.9, preserve=‘single’)) + labs(x=, fill=, y=NULL) + scale_fill_manual(values=colormap.branches, labels=c(‘L’, ‘U’, ‘P’)) + facet_grid(cols=vars(block_branch), switch=‘x’) + scale_y_continuous(limits=c(-0.5, 0.5), breaks=seq(-0.5, 0.5, by=0.5), labels=c(‘100% white’, ‘50/50’, ‘100% brown’)) + theme(strip.background=element_blank(), axis.text.x=element_blank(), strip.placement=‘outside’) p

rr save_plot(‘../figures/figures_paper/main_figures/figure3/BATLAS_results.pdf’, p, base_height=5, base_width=8)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCmBgYHtyfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShtb25vY2xlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShHT3Bsb3QpCmBgYAoKYGBge3J9CnNldXJvYmogPC0gcmVhZFJEUygnLi4vb3V0cHV0L3NldXJhdF9vYmplY3RzLzE4MDgzMS8xMHgtMTgwODMxJykKY2RzIDwtIHJlYWRSRFMoJy4uL291dHB1dC9tb25vY2xlLzE4MDgzMS8xMHgtMTgwODMxLW1vbm9jbGUtbW9ub2NsZV9nZW5lbGlzdF9UMVQyVDNfVDRUNV9yZXMuMS41JykKdDFfYWxpZ25lZCA8LSByZWFkUkRTKCcuLi9vdXRwdXQvc2V1cmF0X29iamVjdHMvMTgwNTA0LzEweC0xODA1MDQtY2NyZWdvdXQtYWxpZ25lZCcpCnNvdXJjZSgnLi4vY29kZS9jb2xvcnMuUicpCmBgYAoKI0ZpZ3VyZSAxCgpgYGB7ciBlY2hvPVQsIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZ9CnAxIDwtIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSdkZXBvdCcsIGNvbG9ycy51c2U9Y29sb3JzLmRlcG90cywgcHQuc2l6ZT0wLjEsIG5vLmF4ZXM9VCkKCnAyIDwtIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSd0aW1lcG9pbnQnLCBjb2xvcnMudXNlPWNvbG9ycy50aW1lcG9pbnRzLCBwdC5zaXplPTAuNSwgbm8uYXhlcz1GLCBkby5yZXR1cm49VCkgKyB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIHBsb3QubWFyZ2luPWdyaWQ6OnVuaXQoYygwLDAsMCwwKSwgIm1tIikpCgp0MV9hbGlnbmVkIDwtIFNldEFsbElkZW50KHQxX2FsaWduZWQsIGlkPSdkZXBvdCcpCnQxX2FsaWduZWRAaWRlbnQgPC0gZmFjdG9yKHQxX2FsaWduZWRAaWRlbnQsIGxldmVscz1jKCdTdXByYScsICdTdWJxJywgJ1BlcmknLCAnVmlzY2UnKSkKCnAzIDwtIFRTTkVQbG90KHQxX2FsaWduZWQsIGdyb3VwLmJ5PSdkZXBvdCcsIGNvbG9ycy51c2U9Y29sb3JzLmRlcG90cywgZG8ucmV0dXJuPVQsIHB0LnNpemU9MC41LCBuby5heGVzPVQpCgpwMyRkYXRhIDwtIHAzJGRhdGEgJT4lIG11dGF0ZShpZGVudD1mYWN0b3IoaWRlbnQsIGxldmVscz1jKCdWaXNjZScsICdTdXByYScsICdTdWJxJywgJ1BlcmknKSkpICU+JSBhcnJhbmdlCgpmaWcxIDwtIHBsb3RfZ3JpZChwMSwgcDIsIHAzLCBuY29sPTIpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTIsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQpmaWcxCmBgYAoKYGBge3J9CnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUxX292ZXJ2aWV3LzEweC0xODA4MzFfdHNuZV9kZXBvdHMucGRmIiwgcDEsIGJhc2Vfd2lkdGg9NiwgYmFzZV9oZWlnaHQ9NC41KQpzYXZlX3Bsb3QoIi4uL2ZpZ3VyZXMvZmlndXJlc19wYXBlci9tYWluX2ZpZ3VyZXMvRmlndXJlMV9vdmVydmlldy8xMHgtMTgwODMxX3RzbmVfdGltZXBvaW50cy5wZGYiLCBwMiwgYmFzZV93aWR0aD00LCBiYXNlX2hlaWdodD0zKQpzYXZlX3Bsb3QoIi4uL2ZpZ3VyZXMvZmlndXJlc19wYXBlci9tYWluX2ZpZ3VyZXMvRmlndXJlMV9vdmVydmlldy8xMHgtMTgwODMxX3RzbmVfdDFfYWxpZ25lZC5wZGYiLCBwMywgYmFzZV93aWR0aD02LCBiYXNlX2hlaWdodD00LjUpCmBgYAoKCiNGaWd1cmUgMgoKCmBgYHtyIGVjaG89VCwgcmVzdWx0cz0naGlkZScsIGluY2x1ZGU9Rn0KIzEweC0xODA4MzFfdHNuZV9kZXBvdHMKIzEweC0xODA4MzFfdHNuZV90aW1lcG9pbnRzCiMxMHgtMTgwODMxX3RyYWplY3RvcnlfZGVwb3RzCiMxMHgtMTgwODMxX3RyYWplY3RvcnlfdGltZXBvaW50cwojMTB4LTE4MDgzMV90c25lX3N0YXRlCgp0cmFqX1QgPC0gcGxvdF9jZWxsX3RyYWplY3RvcnkoY2RzLCBjb2xvcl9ieSA9ICJ0aW1lcG9pbnQiKSArIGdlb21fcG9pbnQoY29sb3I9J3doaXRlJywgc2l6ZT01KSArIGdlb21fcG9pbnQoYWVzKGNvbG91cj10aW1lcG9pbnQpLCBhbHBoYT0wLjEpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2xvcnMudGltZXBvaW50cykgKyB0aGVtZShsZWdlbmQucG9zaXRpb249J2JvdHRvbScpCgp0c25lX2JyYW5jaGVzIDwtIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSdTdGF0ZS5sYWJlbHMnLCBjb2xvcnMudXNlPWNvbG9ycy5zdGF0ZXMubGFiZWxzLCBuby5heGVzPVQsIHB0LnNpemU9cHQuc2l6ZS50c25lKSArIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uPSd0b3AnKQoKdHJhal9wdCA8LSBwbG90X2NlbGxfdHJhamVjdG9yeShjZHMsIGNvbG9yX2J5PSdQc2V1ZG90aW1lX3N0cmV0Y2hlZCcsIHNob3dfYnJhbmNoX3BvaW50cyA9IEYsIHNob3dfYmFja2JvbmU9RikgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93PScjOTBkOGYyJywgaGlnaD0nIzAwNjQ4OCcsIG5hbWU9J1BzZXVkb3RpbWVcbihzdHJldGNoZWQpJywgYnJlYWtzPWMoMCwgNTAsIDEwMCkpICsgdGhlbWVfdm9pZCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ3JpZ2h0JywgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTYpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLCBsZWdlbmQua2V5LnNpemU9dW5pdCgwLjYsICdjbScpKQoKZnBfcHQgPC0gRmVhdHVyZVBsb3Qoc2V1cm9iaiwgZmVhdHVyZXMucGxvdD0nUHNldWRvdGltZV9zdHJldGNoZWQnLCBjb2xzLnVzZT1jKCcjOTBkOGYyJywgJyMwMDcxOWEnKSwgZG8ucmV0dXJuPVQsIG5vLmF4ZXM9VCwgcHQuc2l6ZT0xLCBuby5sZWdlbmQ9RikkUHNldWRvdGltZV9zdHJldGNoZWQgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93PScjOTBkOGYyJywgaGlnaD0nIzAwNjQ4OCcsIG5hbWU9J1BzZXVkb3RpbWVcbihzdHJldGNoZWQpJykgKyB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTIwKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApLCBsZWdlbmQua2V5LmhlaWdodD11bml0KDEuMywgJ2NtJykpCgp0c25lX2RlcG90IDwtIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSdkZXBvdCcsIGNvbG9ycy51c2U9Y29sb3JzLmRlcG90cywgcHQuc2l6ZT1wdC5zaXplLnRzbmUsIG5vLmF4ZXM9RikgKyB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMyksIGxlZ2VuZC5rZXkuaGVpZ2h0PXVuaXQoMC43LCAnY20nKSwgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBwbG90Lm1hcmdpbj1ncmlkOjp1bml0KGMoMCwwLDAsMCksICJtbSIpKQoKZmlnMiA8LSBwbG90X2dyaWQoCiAgdHJhal9ULCB0c25lX2JyYW5jaGVzLCB0cmFqX3B0LCBmcF9wdCwgdHNuZV9kZXBvdCwgbmNvbD0yCikKYGBgCgpgYGB7ciwgZmlnLmhlaWdodCA9IDE1LCBmaWcud2lkdGggPSAxMiwgZmlnLmFsaWduID0gImNlbnRlciJ9CmZpZzIKYGBgCgoKYGBge3IgZWNobz1ULCByZXN1bHRzPSdoaWRlJywgaW5jbHVkZT1GfQojdHJhal9ULCB0c25lX2JyYW5jaGVzLCB0cmFqX3B0LCBmcF9wdCwgdHNuZV9kZXBvdCwgbmNvbD0yCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUyX21vbm9jbGUvMTB4LTE4MDgzMV90cmFqZWN0b3J5X3RpbWVwb2ludHMucGRmIiwgdHJhal9ULCBiYXNlX3dpZHRoPTYsIGJhc2VfaGVpZ2h0PTQuNSkKCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUyX21vbm9jbGUvMTB4LTE4MDgzMV90c25lX2JyYW5jaC5wZGYiLCB0c25lX2JyYW5jaGVzLCBiYXNlX3dpZHRoPTUsIGJhc2VfaGVpZ2h0PTQuNSkKCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUyX21vbm9jbGUvMTB4LTE4MDgzMV90cmFqZWN0b3J5X3BzZXVkb3RpbWUucGRmIiwgdHJhal9wdCwgYmFzZV93aWR0aD01LCBiYXNlX2hlaWdodD0yKQoKc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL0ZpZ3VyZTJfbW9ub2NsZS8xMHgtMTgwODMxX3RzbmVfcHNldWRvdGltZS5wZGYiLCBmcF9wdCwgYmFzZV93aWR0aD01LjIsIGJhc2VfaGVpZ2h0PTMuNSkKCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUyX21vbm9jbGUvMTB4LTE4MDgzMV90c25lX2RlcG90LnBkZiIsIHRzbmVfZGVwb3QsIGJhc2Vfd2lkdGg9My4zLCBiYXNlX2hlaWdodD0yLjI1KQpgYGAKCgojRmlndXJlIDMKCiMjSGVhdG1hcAoKSGVhdG1hcAoKYGBge3IsIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSA2LCBmaWcuYWxpZ24gPSAiY2VudGVyIn0KbG9hZCgnLi4vb3V0cHV0L21vbm9jbGUvMTgwODMxL2hlYXRtYXBzJykKaGVhdG1hcCA8LSBoZWF0bWFwcyRoZWF0bWFwX2xvZ0ZDMC4zX25jbHVzdGVyNl9maWx0ZXJlZF9nZW5lcwpncmlkRXh0cmE6OmdyaWQuYXJyYW5nZShoZWF0bWFwJHBoX3JlcyRndGFibGUpCmBgYAoKYGBge3J9CnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL0JFQU1faGVhdG1hcF9sb2dGQzAuM19uY2x1c3RlcjZfZmlsdGVyZWRfZ2VuZXMucGRmIiwgaGVhdG1hcCRwaF9yZXMkZ3RhYmxlLCBiYXNlX3dpZHRoPTcsIGJhc2VfaGVpZ2h0PTgpCmBgYAoKIyNQc2V1ZG90aW1lIHBsb3RzCgpQc2V1ZG90aW1lIHBsb3RzCgpgYGB7cn0KI25ld19jZHMgPC0gYnVpbGRCcmFuY2hDZWxsRGF0YVNldChjZHMsIHByb2dlbml0b3JfbWV0aG9kPSdkdXBsaWNhdGUnLCBicmFuY2hfc3RhdGVzPWMoMiwzKSwgYnJhbmNoX3BvaW50PTEsIGJyYW5jaF9sYWJlbHM9YygnTWV0YWJvbGljJywgJ0VDTScpLCBzdHJldGNoPVQpCiNzYXZlUkRTKG5ld19jZHMsIGZpbGU9Jy4uL291dHB1dC9tb25vY2xlLzE4MDgzMS8xMHgtMTgwODMxLW1vbm9jbGUtbW9ub2NsZV9nZW5lbGlzdF9UMVQyVDNfVDRUNV9yZXMuMS41X2R1cGxpY2F0ZWQtcHJvZ2VuaXRvcl9zdHJldGNoZWQtcHNldWRvdGltZScpCgpuZXdfY2RzIDwtIHJlYWRSRFMoJy4uL291dHB1dC9tb25vY2xlLzE4MDgzMS8xMHgtMTgwODMxLW1vbm9jbGUtbW9ub2NsZV9nZW5lbGlzdF9UMVQyVDNfVDRUNV9yZXMuMS41X2R1cGxpY2F0ZWQtcHJvZ2VuaXRvcl9zdHJldGNoZWQtcHNldWRvdGltZScpCiNuZXcgY2RzIGNvbnRhaW5zIGR1cGxpY2F0ZWQgcHJvZ2VuaXRvciBjZWxscyAob25lIGFzc2lnbmVkIHRvIGVhY2ggYnJhbmNoKSBhbmQgc3RyZXRjaGVkIFBzZXVkb3RpbWUKCmRmX3BkYXRhIDwtIHBEYXRhKG5ld19jZHMpW2MoJ29yaWdpbmFsX2NlbGxfaWQnLCAnQnJhbmNoJywgJ1N0YXRlLmxhYmVscycsICdQc2V1ZG90aW1lJyldCgojZ2V0IGV4cHJlc3Npb24gdmFsdWVzIGZvciBldmVyeSBjZWxsIElEIGZyb20gdGhlIG5ldyBjZHMKZ2VuZXMgPC0gYXMubWF0cml4KHQoc2V1cm9iakBkYXRhW2MoJ0FESVBPUScsICdNR1AnLCAnVUNQMicsICdEQ04nLCAnQVBPRCcpLCBkZl9wZGF0YSRvcmlnaW5hbF9jZWxsX2lkXSkpCgojY2JpbmQgdGhlIGV4cHJlc3Npb24gdmFsdWVzIHdpdGggdGhlIHJlbGV2YW50IG1ldGFkYXRhCmRmIDwtIGNiaW5kKGRmX3BkYXRhLCBhcy5kYXRhLmZyYW1lKGdlbmVzKSkKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQgPSA4LCBmaWcud2lkdGggPSAxMCwgZmlnLmFsaWduID0gImNlbnRlciJ9CnBsb3RfcHNldWRvdGltZSA8LSBmdW5jdGlvbihnZW5lLCBsZWdlbmQpewogIHAgPC0gZ2dwbG90KGRmLCBhZXNfc3RyaW5nKHg9J1BzZXVkb3RpbWUnLCB5PWdlbmUpKSArCiAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAxLCBzdHJva2UgPSAwLCBhbHBoYT0wLjIsIGFlcyhmaWxsPVN0YXRlLmxhYmVscyksIHNob3cubGVnZW5kPUYpCiAgCiAgaWYgKGxlZ2VuZCl7CiAgICBwIDwtIHAgKyBnZW9tX3Ntb290aChzZSA9IEZBTFNFLCBhZXMoY29sb3I9QnJhbmNoKSwgc3Bhbj0wLjksIG1ldGhvZD0nbG9lc3MnLCBzaXplPTIpCiAgfSBlbHNlIHsKICAgIHAgPC0gcCArIGdlb21fc21vb3RoKHNlID0gRkFMU0UsIGFlcyhjb2xvcj1CcmFuY2gpLCBzcGFuPTAuOSwgbWV0aG9kPSdsb2VzcycsIHNpemU9Miwgc2hvdy5sZWdlbmQ9RikKICB9CiAgcCA8LSBwICsgCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbG9ycy5wc2V1ZG90aW1lLmxpbmVzKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sb3JzLnBzZXVkb3RpbWUucG9pbnRzKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobWlub3JfYnJlYWtzPTEpICsKICAgIHhsYWIoJ1BzZXVkb3RpbWUgKHN0cmV0Y2hlZCknKSArCiAgICBnZ3RpdGxlKGdlbmUpICsKICAgIHlsYWIoJ0V4cHJlc3Npb24nKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MzApLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0zMCksIGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNSksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MjApLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MzApLCBsZWdlbmQua2V5LnNpemU9dW5pdCgxLjUsICdjbScpKQogIHJldHVybihwKQp9CgphZGlwb3FfcHQgPC0gcGxvdF9wc2V1ZG90aW1lKCdBRElQT1EnLCBsZWdlbmQ9RikKdWNwMl9wdCA8LSBwbG90X3BzZXVkb3RpbWUoJ1VDUDInLCBsZWdlbmQ9VCkKZGNuX3B0IDwtIHBsb3RfcHNldWRvdGltZSgnRENOJywgbGVnZW5kPUYpCmFwb2RfcHQgPC0gcGxvdF9wc2V1ZG90aW1lKCdBUE9EJywgbGVnZW5kPVQpCgptZXRhYm9saWNfcHQgPC0gcGxvdF9ncmlkKGFkaXBvcV9wdCwgdWNwMl9wdCwgbmNvbD0yLCByZWxfd2lkdGhzPWMoMC40MTUsIDAuNTg1KSkKZWNtX3B0IDwtIHBsb3RfZ3JpZChkY25fcHQsIGFwb2RfcHQsIG5jb2w9MiwgcmVsX3dpZHRocz1jKDAuNDE1LCAwLjU4NSkpCgpwbG90X2dyaWQobWV0YWJvbGljX3B0LCBlY21fcHQsIG5jb2w9MSkKYGBgCgpgYGB7cn0Kd2lkdGg9MTIKaGVpZ2h0PTUKCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUzX2JlYW0vcHNldWRvdGltZV9tZXRhYm9saWMucGRmIiwgbWV0YWJvbGljX3B0LCBiYXNlX3dpZHRoPXdpZHRoLCBiYXNlX2hlaWdodD1oZWlnaHQpCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUzX2JlYW0vcHNldWRvdGltZV9lY20ucGRmIiwgZWNtX3B0LCBiYXNlX3dpZHRoPXdpZHRoLCBiYXNlX2hlaWdodD1oZWlnaHQpCgoKI3NhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL3BzZXVkb3RpbWVfQURJUE9RLnBkZiIsIGFkaXBvcV9wdCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQojc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL2ZpZ3VyZTMvcHNldWRvdGltZV9VQ1AyLnBkZiIsIHVjcDJfcHQsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKI3NhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL3BzZXVkb3RpbWVfRENOLnBkZiIsIGRjbl9wdCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQojc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL2ZpZ3VyZTMvcHNldWRvdGltZV9BUE9ELnBkZiIsIGFwb2RfcHQsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKYGBgCgojI0ZlYXR1cmVwbG90cwoKYGBge3IgZWNobz1ULCByZXN1bHRzPSdoaWRlJ30KZ2VuZXMgPC0gYygnQURJUE9RJywgJ1VDUDInLCAnRENOJywgJ0FQT0QnKQpmZWF0dXJlcGxvdHNfbm9sZWcgPC0gRmVhdHVyZVBsb3Qoc2V1cm9iaiwgZmVhdHVyZXMucGxvdD1nZW5lcywgY29scy51c2U9YygnZ3JheScsICdibHVlJyksIG5vLmxlZ2VuZD1ULCBkby5yZXR1cm49VCwgbm8uYXhlcz1ULCBwdC5zaXplPTEsIG1heC5jdXRvZmY9Yyg1KSkgCmZlYXR1cmVwbG90c19sZWcgPC0gRmVhdHVyZVBsb3Qoc2V1cm9iaiwgZmVhdHVyZXMucGxvdD1nZW5lcywgY29scy51c2U9YygnZ3JheScsICdibHVlJyksIG5vLmxlZ2VuZD1GLCBkby5yZXR1cm49VCwgbm8uYXhlcz1ULCBwdC5zaXplPTEsIG1heC5jdXRvZmY9Yyg1KSkgCgphZGlwb3FfZnAgPC0gZmVhdHVyZXBsb3RzX25vbGVnJEFESVBPUSArIHRoZW1lKHBsb3QudGl0bGU9ZWxlbWVudF9ibGFuaygpKQoKdWNwMl9mcCA8LSBmZWF0dXJlcGxvdHNfbGVnJFVDUDIgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChuYW1lPSdFeHByZXNzaW9uJywgbG93PSdncmF5JywgaGlnaD0nYmx1ZScsIGd1aWRlPSdjb2xvcmJhcicsIGxpbWl0cz1jKDAsNSkpICsgdGhlbWUocGxvdC50aXRsZT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0yMCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSwgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDEuMywgJ2NtJykpCgpkY25fZnAgPC0gZmVhdHVyZXBsb3RzX25vbGVnJERDTiArIHRoZW1lKHBsb3QudGl0bGU9ZWxlbWVudF9ibGFuaygpKQoKYXBvZF9mcCA8LSBmZWF0dXJlcGxvdHNfbGVnJEFQT0QgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChuYW1lPSdFeHByZXNzaW9uJywgbG93PSdncmF5JywgaGlnaD0nYmx1ZScsIGd1aWRlPSdjb2xvcmJhcicpICsgdGhlbWUocGxvdC50aXRsZT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0yMCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSwgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDEuMywgJ2NtJykpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTIsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQptZXRhYm9saWNfZnAgPC0gcGxvdF9ncmlkKGFkaXBvcV9mcCwgdWNwMl9mcCwgbmNvbD0yLCByZWxfd2lkdGhzPWMoMC40MSwgMC41OSkpCmVjbV9mcCA8LSBwbG90X2dyaWQoZGNuX2ZwLCBhcG9kX2ZwLCBuY29sPTIsIHJlbF93aWR0aHM9YygwLjQxLCAwLjU5KSkKCnBsb3RfZ3JpZChtZXRhYm9saWNfZnAsIGVjbV9mcCwgbmNvbD0xKQpgYGAKCgpgYGB7cn0KCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUzX2JlYW0vZmVhdHVyZXBsb3RzX21ldGFib2xpYy5wZGYiLCBtZXRhYm9saWNfZnAsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL0ZpZ3VyZTNfYmVhbS9mZWF0dXJlcGxvdHNfZWNtLnBkZiIsIGVjbV9mcCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQoKI3NhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL2ZlYXR1cmVwbG90X0FESVBPUS5wZGYiLCBhZGlwb3FfZnAsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKI3NhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL2ZlYXR1cmVwbG90X1VDUDIucGRmIiwgdWNwMl9mcCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQojc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL2ZpZ3VyZTMvZmVhdHVyZXBsb3RfRENOLnBkZiIsIGRjbl9mcCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQojc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL2ZpZ3VyZTMvZmVhdHVyZXBsb3RfQVBPRC5wZGYiLCBhcG9kX2ZwLCBiYXNlX3dpZHRoPXdpZHRoLCBiYXNlX2hlaWdodD1oZWlnaHQpCmBgYAoKIyNHTyBidWJibGUgcGxvdAoKYGBge3J9Cm5hbWUgPC0gJ2hlYXRtYXBfbG9nRkMwLjNfbmNsdXN0ZXI2Jwpmb2xkZXIgPC0gcGFzdGUoJy4uL3RhYmxlcy90YWJsZXNfcGFwZXIvYWxsX3RhYmxlcy9CRUFNLycsIG5hbWUsIHNlcD0nJykKI2NsdXN0ZXJzIDwtIGMoMSwyLDMsNCw2KQpjbHVzdGVycyA8LSBjKDIsNiwzKQpnc2VhIDwtIGxpc3QoKQpnZW5lbGlzdCA8LSBsaXN0KCkKCmZvciAoaSBpbiBjbHVzdGVycyl7CiAgZ3NlYV9jbHVzdGVyIDwtIHJlYWQudGFibGUocGFzdGUoZm9sZGVyLCAnL1JFVklHT19jbGVhbmVkLycsICdSRVZJR09fY2x1c3RlcicsIGksICdfY2xlYW5lZC50c3YnLCBzZXA9JycpLCBoZWFkZXI9VCkKICBnc2VhX2NsdXN0ZXJbJ2NsdXN0ZXInXSA8LSBpCiAgZ2VuZXNfY2x1c3RlciA8LSByZWFkLnRhYmxlKHBhc3RlKGZvbGRlciwgJy9nZW5lbGlzdF9jbHVzdGVyJywgaSwgJy50c3YnLCBzZXA9JycpLCBoZWFkZXI9VCkKICBnc2VhW1tpXV0gPC0gZ3NlYV9jbHVzdGVyCiAgZ2VuZWxpc3RbW2ldXSA8LSBnZW5lc19jbHVzdGVyCn0KCmdzZWEgPC0gZG8uY2FsbCgicmJpbmQiLCBnc2VhKQpnZW5lbGlzdCA8LSBkby5jYWxsKCJyYmluZCIsIGdlbmVsaXN0KQoKY3JlYXRlX3Rlcm1zIDwtIGZ1bmN0aW9uKGdzZWEpewogIHJldHVybihkYXRhLmZyYW1lKGNhdGVnb3J5PWdzZWEkZ3NlYS5kb21haW4sIElEPWdzZWEkcmV2aWdvLnRlcm1fSUQsIHRlcm09Z3NlYSRyZXZpZ28uZGVzY3JpcHRpb24sIGFkal9wdmFsPWdzZWEkZ3NlYS5wLnZhbHVlLCBnZW5lcz1nc2VhJGdzZWEuaW50ZXJzZWN0aW9uLCBjbHVzdGVyPWdzZWEkY2x1c3RlcikpCn0KCmNyZWF0ZV9nZW5lcyA8LSBmdW5jdGlvbihnZW5lbGlzdCl7CiAgcmV0dXJuKGRhdGEuZnJhbWUoSUQ9Z2VuZWxpc3QkZ2VuZV9zaG9ydF9uYW1lLCBsb2dGQz1nZW5lbGlzdCRhdmdMb2dGQ19TdGF0ZTJfU3RhdGUzKSkKfQoKdGVybXMgPC0gY3JlYXRlX3Rlcm1zKGdzZWEpCmdlbmVzIDwtIGNyZWF0ZV9nZW5lcyhnZW5lbGlzdCkKY2lyYyA8LSBjaXJjbGVfZGF0KHRlcm1zLCBnZW5lcykKCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSAyMCwgZmlnLmFsaWduID0gImNlbnRlciJ9CkdPQnViYmxlX21vZGlmaWVkIDwtIGZ1bmN0aW9uKGRhdGEsIGRpc3BsYXksIHRpdGxlLCBjb2xvdXIsIGxhYmVscywgSUQgPSBULCB0YWJsZS5sZWdlbmQgPSBULCB0YWJsZS5jb2wgPSBULCBiZy5jb2wgPSBGLCB6c2NvcmVfdGhyZXNob2xkPTAsIGdncmVwZWxfbGluZWNvbD0nYmxhY2snLCB0ZXh0X3NpemVfYXhlcz0yMCwgdGV4dF9zaXplX2F4ZXNfbGFiZWw9MjAsIHRleHRfc2l6ZT0xMCwgdGV4dF9zaXplX2xlZ2VuZD03LCB0ZXh0X3NpemVfdGhyZXNob2xkPTEwLCBsZWdlbmRfcG9pbnRfc2l6ZT0yMCl7CiAgenNjb3JlIDwtIGFkal9wdmFsIDwtIGNhdGVnb3J5IDwtIGNvdW50IDwtIGlkIDwtIHRlcm0gPC0gTlVMTAogIGlmIChtaXNzaW5nKGRpc3BsYXkpKSBkaXNwbGF5IDwtICdzaW5nbGUnCiAgaWYgKG1pc3NpbmcodGl0bGUpKSB0aXRsZSA8LSAnJwogIGlmIChtaXNzaW5nKGNvbG91cikpIGNvbHMgPC0gYygiY2hhcnRyZXVzZTQiLCAiYnJvd24yIiwgImNvcm5mbG93ZXJibHVlIikgZWxzZSBjb2xzIDwtIGNvbG91cgogIGlmIChtaXNzaW5nKGxhYmVscykpIGxhYmVscyA8LSA1CiAgaWYgKGJnLmNvbCA9PSBUICYgZGlzcGxheSA9PSAnc2luZ2xlJykgY2F0KCJQYXJhbWV0ZXIgYmcuY29sIHdpbGwgYmUgaWdub3JlZC4gVG8gdXNlIHRoZSBwYXJhbWV0ZXIgY2hhbmdlIGRpc3BsYXkgdG8gJ211bHRpcGxlJyIpCiAgCiAgY29sbmFtZXMoZGF0YSkgPC0gdG9sb3dlcihjb2xuYW1lcyhkYXRhKSkKICB0bXBfbGFiIDwtIGRhdGEuZnJhbWUoY2F0cyA9IGMoJ0Jpb2xvZ2ljYWwgUHJvY2VzcycsICdDZWxsdWxhciBDb21wb25lbnQnLCAnTW9sZWN1bGFyIEZ1bmN0aW9uJyksIAogICAgICAgICAgICAgICAgICAgICAgICBjYXQuYWJiID0gYygnQlAnLCAnQ0MnLCAnTUYnKSwKICAgICAgICAgICAgICAgICAgICAgICAgbG9jeSA9IGMobWF0Y2goJ0JQJywgZGF0YSRjYXRlZ29yeSksIG1hdGNoKCdDQycsIGRhdGEkY2F0ZWdvcnkpLCBtYXRjaCgnTUYnLCBkYXRhJGNhdGVnb3J5KSksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHMgPSBjb2xzLAogICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRikKICB0bXBfbGFiIDwtIHRtcF9sYWJbb3JkZXIodG1wX2xhYiRsb2N5KSxdCiAgaWYoISdjb3VudCclaW4lY29sbmFtZXMoZGF0YSkpewogICAgcmFuZyA8LSBjKDUsIDUpCiAgICBkYXRhJGNvdW50IDwtIHJlcCgxLCBkaW0oZGF0YSlbMV0pCiAgfWVsc2Uge3JhbmcgPC0gYygxLCAzMCl9CiAgZGF0YSRhZGpfcHZhbCA8LSAtbG9nKGRhdGEkYWRqX3B2YWwsIDEwKQogIHN1YiA8LSBkYXRhWyFkdXBsaWNhdGVkKGRhdGEkdGVybSksIF0KICBnIDwtIGdncGxvdChzdWIsIGFlcyh6c2NvcmUsIGFkal9wdmFsLCBmaWxsID0gY2F0ZWdvcnksIHNpemUgPSBjb3VudCkpKwogICAgbGFicyh0aXRsZSA9IHRpdGxlLCB4ID0gJ3otc2NvcmUnLCB5ID0gJy1sb2cgKGFkaiBwLXZhbHVlKScpKwogICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2wgPSAnYmxhY2snLCBhbHBoYSA9IDEgLyAyKSsgI2FkZCBhbGwgYnViYmxlcwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMS4zLCBjb2wgPSAnb3JhbmdlJykrICNhZGQgdGhyZXNob2xkIGZvciBwLXZhbHVlPTAuMDUKICAgIHNjYWxlX3NpemUocmFuZ2UgPSByYW5nLCBndWlkZSA9ICdub25lJykgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsNDUpKQogIAogIHN1YjIgPC0gc3Vic2V0KHN1Yiwgc3Vic2V0PXN1YiRhZGpfcHZhbCA+PSBsYWJlbHMpCiAgc3ViMiA8LSBzdWJzZXQoc3ViMiwgc3Vic2V0PWFicyhzdWIyJHpzY29yZSkgPj0genNjb3JlX3RocmVzaG9sZCkKCiAgICBnIDwtIGcgKyBzY2FsZV9maWxsX21hbnVhbCgnJywgdmFsdWVzID0gdG1wX2xhYiRjb2xzLCBsYWJlbHMgPSB0bXBfbGFiJGNhdHMpKwogICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAncmlnaHQnLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEsICdjbScpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KGZhY2U9J2JvbGQnKSkgKwogICAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9bGVnZW5kX3BvaW50X3NpemUpKSkKICAgICAgYW5ub3RhdGUgKCJ0ZXh0IiwgeCA9IDAuNiwgeSA9IDIuMiwgbGFiZWwgPSAiVGhyZXNob2xkIiwgY29sb3VyID0gIm9yYW5nZSIsIHNpemUgPSB0ZXh0X3NpemVfdGhyZXNob2xkKQogICAgZyA8LSBnICsgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSBzdWIyLCBhZXMoeCA9IHpzY29yZSwgeSA9IGFkal9wdmFsLCBsYWJlbCA9IHRlcm0pLCBzaXplID0gdGV4dF9zaXplLCBzZWdtZW50LmNvbG9yID0gZ2dyZXBlbF9saW5lY29sKQogICAgZyA8LSAgZyArIAogICAgICAgIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gdGV4dF9zaXplX2F4ZXMpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gJ2dyZXk4MCcpLCBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICdncmV5ODAnKSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gdGV4dF9zaXplX2F4ZXNfbGFiZWwsIGZhY2UgPSAnYm9sZCcpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPXRleHRfc2l6ZV9sZWdlbmQpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9dGV4dF9zaXplX2xlZ2VuZCkpCiByZXR1cm4oZykKfQoKcCA8LSBHT0J1YmJsZV9tb2RpZmllZChjaXJjLCBsYWJlbHM9MiwgSUQ9RiwgdGFibGUubGVnZW5kID0gRiwgenNjb3JlX3RocmVzaG9sZD00LjUsIGdncmVwZWxfbGluZWNvbD0ndHJhbnNwYXJlbnQnLCB0ZXh0X3NpemVfYXhlcz0xNSwgdGV4dF9zaXplX2F4ZXNfbGFiZWw9MTUsIHRleHRfc2l6ZT00LjUsIHRleHRfc2l6ZV9sZWdlbmQ9MTUsIHRleHRfc2l6ZV90aHJlc2hvbGQ9NSwgbGVnZW5kX3BvaW50X3NpemU9MTUpCnAKYGBgCgpgYGB7cn0Kc2F2ZV9wbG90KCcuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL0ZpZ3VyZTNfYmVhbS8xODA4MzFfYmVhbUdPX2NsdXN0ZXItMi02LTMucGRfbGFiZWxzM196c2NvcmU0LjUucGRmJywgcCwgYmFzZV93aWR0aD0yMCwgYmFzZV9oZWlnaHQ9NykKI3NhdmVfcGxvdCgnLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUzX2JlYW0vMTgwODMxX2JlYW1HT19hbGwtdGVybXMucGRfbGFiZWxzM196c2NvcmU0LjUucGRmJywgcCwgYmFzZV93aWR0aD0yMCwgYmFzZV9oZWlnaHQ9NykKYGBgCgojUGVyY2VudC5taXRvCgpgYGB7ciBlY2hvPVQsIHJlc3VsdHM9J2hpZGUnfQpwZXJjZW50X21pdG9fZnAgPC0gRmVhdHVyZVBsb3Qoc2V1cm9iaiwgZmVhdHVyZXMucGxvdD1jKCdwZXJjZW50Lm1pdG8uMTAwJyksIGNvbHMudXNlPWMoJ2dyYXknLCAnYmx1ZScpLCBuby5sZWdlbmQ9RiwgZG8ucmV0dXJuPVQsIG5vLmF4ZXM9VCwgbWF4LmN1dG9mZiA9IGMoMTApKSRwZXJjZW50Lm1pdG8gKyBnZ3RpdGxlKCcnKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50KG5hbWU9JyUgbWl0b2Nob25kcmlhbFxuZ2VuZSBleHByZXNzaW9uJywgbG93PSdncmF5JywgaGlnaD0nYmx1ZScsIGd1aWRlPSdjb2xvcmJhcicpICsgdGhlbWUobGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDEuNiwgJ2NtJykpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSA0LCBmaWcud2lkdGggPSA1LjUsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQpwZXJjZW50X21pdG9fZnAKYGBgCgpgYGB7cn0Kc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL0ZpZ3VyZTNfYmVhbS9mZWF0dXJlcGxvdF9QRVJDRU5UX01JVE8ucGRmIiwgcGVyY2VudF9taXRvX2ZwLCBiYXNlX3dpZHRoPXdpZHRoLCBiYXNlX2hlaWdodD1oZWlnaHQpCmBgYAoKI0JBVExBUwoKYGBge3J9CmJhdGxhc19yZXN1bHRzIDwtIHJlYWQudGFibGUoJy4uL3RhYmxlcy90YWJsZXNfcGFwZXIvc3VwcGxlbWVudGFyeV90YWJsZXMvQkFUTEFTL0JBVExBU19icmFuY2hfaGlnaF9yZXMudHh0Jywgc2VwPSdcdCcsIGhlYWRlcj1UKQpiYXRsYXNfcmVzdWx0c1sncHNldWRvdGltZV9kZWNpbGUnXSA8LSBzZXVyb2JqQG1ldGEuZGF0YSRwc2V1ZG90aW1lX2RlY2lsZVttYXRjaChiYXRsYXNfcmVzdWx0cyRzYW1wbGUsIHNldXJvYmpAbWV0YS5kYXRhJGJyYW5jaF9oaWdoX3JlcyldCmJhdGxhc19yZXN1bHRzWydicmFuY2gnXSA8LSBzZXVyb2JqQG1ldGEuZGF0YSRicmFuY2hbbWF0Y2goYmF0bGFzX3Jlc3VsdHMkc2FtcGxlLCBzZXVyb2JqQG1ldGEuZGF0YSRicmFuY2hfaGlnaF9yZXMpXQpiYXRsYXNfcmVzdWx0cyA8LSBiYXRsYXNfcmVzdWx0cyAlPiUgbXV0YXRlKGJsb2NrX2JyYW5jaCA9IGlmX2Vsc2UoYnJhbmNoID09ICdQcm9nZW5pdG9yJywgJ0JlZ2lubmluZycsICdFbmQnKSkKYmF0bGFzX3Jlc3VsdHNbJ2Jyb3duX2NlbnRlcmVkJ10gPC0gYmF0bGFzX3Jlc3VsdHMkYnJvd24gLSAwLjUKYmF0bGFzX3Jlc3VsdHNbJ3JhdGlvJ10gPC0gYmF0bGFzX3Jlc3VsdHMkYnJvd24vYmF0bGFzX3Jlc3VsdHMkd2hpdGUKYGBgCgpgYGB7ciwgZmlnLmhlaWdodCA9IDYsIGZpZy53aWR0aCA9IDgsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQpwIDwtIGdncGxvdChiYXRsYXNfcmVzdWx0cywgYWVzKHg9YXMuZmFjdG9yKHBzZXVkb3RpbWVfZGVjaWxlKSwgeT1icm93bl9jZW50ZXJlZCwgZmlsbD1icmFuY2gpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZTIod2lkdGg9MC45LCBwcmVzZXJ2ZT0nc2luZ2xlJykpICsKICBsYWJzKHg9IlBzZXVkb3RpbWUgKHN0cmV0Y2hlZCkiLCBmaWxsPSJCcmFuY2giLCB5PU5VTEwpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sb3JtYXAuYnJhbmNoZXMsIGxhYmVscz1jKCdMJywgJ1UnLCAnUCcpKSArCiAgZmFjZXRfZ3JpZChjb2xzPXZhcnMoYmxvY2tfYnJhbmNoKSwgc3dpdGNoPSd4JykgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoLTAuNSwgMC41KSwgYnJlYWtzPXNlcSgtMC41LCAwLjUsIGJ5PTAuNSksIGxhYmVscz1jKCcxMDAlIHdoaXRlJywgJzUwLzUwJywgJzEwMCUgYnJvd24nKSkgKwogIHRoZW1lKHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBzdHJpcC5wbGFjZW1lbnQ9J291dHNpZGUnLCBzdHJpcC50ZXh0ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMjAsIHIgPSAwLCBiID0gMCwgbCA9IDApKSkKcApgYGAKCmBgYHtyfQpzYXZlX3Bsb3QoJy4uL2ZpZ3VyZXMvZmlndXJlc19wYXBlci9tYWluX2ZpZ3VyZXMvRmlndXJlM19iZWFtL0JBVExBU19yZXN1bHRzLnBkZicsIHAsIGJhc2VfaGVpZ2h0PTUsIGJhc2Vfd2lkdGg9OCkKYGBgCgoKIyNTT00gRmlndXJlcwoKQ2x1c3RlcnMKClRGIGFuYWx5c2lzCgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMiwgZmlnLmFsaWduID0gImNlbnRlciJ9CmZpZyA8LSBwbG90X2dyaWQoCiAgVFNORVBsb3Qoc2V1cm9iaiwgZ3JvdXAuYnk9J3Jlcy4wLjUnLCBwdC5zaXplPXB0LnNpemUudHNuZSwgZG8ubGFiZWw9VCksCiAgVFNORVBsb3Qoc2V1cm9iaiwgZ3JvdXAuYnk9J3Jlcy4wLjcnLCBwdC5zaXplPXB0LnNpemUudHNuZSwgZG8ubGFiZWw9VCksCiAgVFNORVBsb3Qoc2V1cm9iaiwgZ3JvdXAuYnk9J3Jlcy4xJywgcHQuc2l6ZT1wdC5zaXplLnRzbmUsIGRvLmxhYmVsPVQpLAogIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSdyZXMuMS41JywgcHQuc2l6ZT1wdC5zaXplLnRzbmUsIGRvLmxhYmVsPVQpLAogIG5jb2w9MiwgbGFiZWxzPSdhdXRvJwopCmBgYAoKCk1ldGFib2xpYyBhbmQgRUNNIGdlbmVzCgpgYGB7cn0KCmBgYAoKCmBgYHtyfQpGZWF0dXJlUGxvdChzZXVyb2JqLCBmZWF0dXJlcy5wbG90PSdQc2V1ZG90aW1lJykKYGBgCgo=